﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace WebSocketStressTesting
{
    internal class Main
    {

        private string Ip = "127.0.0.1";
        private int Port = 80;
        private int ConnectNum = 1;

        private bool bool_0;

        private byte[] byte_rtxtFirst;
        private byte[] byte_rtxtAnswer;

        private static ConcurrentQueue<SocketMsg> concurrentQueue = new ConcurrentQueue<SocketMsg>();
        private static object object_0 = new object();
        private static object object_1 = new object();
        private static object object_2 = new object();
        public static int SuccessNum = 0;
        public static int FailNum = 0;
        public static int SendNum = 0;
        public static bool IsAnswer = true;

        public static string[] GetIPAddress()
        {
            List<string> list = new List<string>();
            foreach (IPAddress ipaddress in Dns.GetHostAddresses(Dns.GetHostName()))
            {
                if (ipaddress.AddressFamily.Equals(AddressFamily.InterNetwork))
                {
                    list.Add(ipaddress.ToString());
                }
            }
            return list.ToArray();
        }

        private void CloseSocket(Socket socket)
        {
            try
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
            catch
            {
            }
        }

        private byte[] StringToByte(string str)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(str);
            byte[] array = new byte[bytes.Length + 6];
            array[0] = 129;
            array[1] = Convert.ToByte(bytes.Length);
            array[2] = 26;
            array[3] = 106;
            array[4] = 243;
            array[5] = 100;
            for (int i = 0; i < bytes.Length; i++)
            {
                //byte[] byte1 = BitConverter.GetBytes((bytes[i] ^ array[2 + i % 4]));//将int32转换为字节数组
                //int temp = BitConverter.ToInt32(byte1, 0);
                //Convert.ToByte(temp);
                array[6 + i] = Convert.ToByte((bytes[i] ^ array[2 + i % 4]));
            }
            return array;
        }

        public Main(string Ip, int Port, int ConnectNum)
        {
            //base..ctor();
            this.Ip = Ip;
            this.Port = Port;
            this.ConnectNum = ConnectNum;
        }

        public void SendAnswerData(string rtxtFirst, string rtxtAnswer)
        {
            this.byte_rtxtFirst = this.StringToByte(rtxtFirst);
            this.byte_rtxtAnswer = this.StringToByte(rtxtAnswer);
            for (int i = 0; i < 32; i++)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(this.WaitCallback_Completed));
            }
            IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(this.Ip), this.Port);
            for (int j = 0; j < this.ConnectNum; j++)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(this.WaitCallback_Completed));
                SocketAsyncEventArgs socketAsyncEventArgs = new SocketAsyncEventArgs();
                socketAsyncEventArgs.RemoteEndPoint = remoteEndPoint;
                socketAsyncEventArgs.Completed += this.SocketAsyncEventArgs_Completed;
                if (!Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, socketAsyncEventArgs))
                {
                    this.SocketAsyncEventArgs1_Completed(socketAsyncEventArgs);
                }
            }
        }
        

        private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            SocketAsyncOperation lastOperation = e.LastOperation;
            if (lastOperation == SocketAsyncOperation.Connect)
            {
                this.SocketAsyncEventArgs1_Completed(e);
                return;
            }
            if (lastOperation != SocketAsyncOperation.Receive)
            {
                return;
            }
            this.SocketAsyncEventArgs2_Completed(e);
        }

        private void SocketAsyncEventArgs1_Completed(SocketAsyncEventArgs socketAsyncEventArgs)
        {
            if (socketAsyncEventArgs.SocketError != SocketError.Success)
            {
                this.CloseSocket(socketAsyncEventArgs.ConnectSocket);
                socketAsyncEventArgs.Dispose();
                socketAsyncEventArgs = null;
                lock (object_1)
                {
                    FailNum++;
                }
                return;
            }
            lock (object_0)
            {
                SuccessNum++;
            }
            byte[] bytes = Encoding.UTF8.GetBytes(string.Concat(new object[]
            {
            "GET / HTTP/1.1\r\nHost: ",
            this.Ip,
            ":",
            this.Port,
            "\r\nConnection: Upgrade\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\nOrigin: http://www.blue-zero.com\r\nSec-WebSocket-Version: 13\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\nSec-WebSocket-Key: LeChHPIg320kbqY1XoEWww==\r\nSec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n"
            }));
            socketAsyncEventArgs.SetBuffer(bytes, 0, bytes.Length);
            try
            {
                socketAsyncEventArgs.ConnectSocket.SendAsync(socketAsyncEventArgs);
            }
            catch
            {
            }
            SocketAsyncEventArgs socketAsyncEventArgs1 = new SocketAsyncEventArgs();
            socketAsyncEventArgs1.Completed += this.SocketAsyncEventArgs_Completed;
            socketAsyncEventArgs1.SetBuffer(new byte[1024], 0, 1024);
            socketAsyncEventArgs1.AcceptSocket = socketAsyncEventArgs.ConnectSocket;
            if (!socketAsyncEventArgs1.AcceptSocket.ReceiveAsync(socketAsyncEventArgs1))
            {
                this.SocketAsyncEventArgs2_Completed(socketAsyncEventArgs1);
            }
        }

        private void SocketAsyncEventArgs2_Completed(SocketAsyncEventArgs socketAsyncEventArgs)
        {
            if (socketAsyncEventArgs.SocketError == SocketError.Success && socketAsyncEventArgs.BytesTransferred != 0)
            {
                int len = socketAsyncEventArgs.BytesTransferred;
                byte[] data_pac = new byte[len];
                Array.Copy(socketAsyncEventArgs.Buffer, socketAsyncEventArgs.Offset, data_pac, 0, len);
                Func<bool, byte[]> func = delegate (bool ok)
                {
                    byte[] array2;
                    if (socketAsyncEventArgs.UserToken != null)
                    {
                        byte[] array = (byte[])socketAsyncEventArgs.UserToken;
                        array2 = new byte[len + array.Length];
                        Array.Copy(array, 0, array2, 0, array.Length);
                        Array.Copy(data_pac, 0, array2, array.Length, len);
                        if (ok)
                        {
                            socketAsyncEventArgs.UserToken = null;
                        }
                    }
                    else
                    {
                        array2 = data_pac;
                    }
                    return array2;
                };
                if (socketAsyncEventArgs.AcceptSocket.Available != 0)
                {
                    socketAsyncEventArgs.UserToken = func(false);
                }
                else
                {
                    SocketAsyncEventArgs socketAsyn = new SocketAsyncEventArgs();
                    socketAsyn.AcceptSocket = socketAsyncEventArgs.AcceptSocket;
                    SocketMsg item = new SocketMsg(func(true), len, socketAsyn);
                    concurrentQueue.Enqueue(item);
                }
                if (!socketAsyncEventArgs.AcceptSocket.ReceiveAsync(socketAsyncEventArgs))
                {
                    this.SocketAsyncEventArgs2_Completed(socketAsyncEventArgs);
                }
                return;
            }
            this.CloseSocket(socketAsyncEventArgs.AcceptSocket);
            socketAsyncEventArgs = null;
        }

        private void WaitCallback_Completed(object object_3)
        {
            while (!this.bool_0)
            {
                SocketMsg socketMsg = null;
                concurrentQueue.TryDequeue(out socketMsg);
                if (socketMsg != null)
                {
                    if (Encoding.UTF8.GetString(socketMsg.byte_0, 0, socketMsg.bytesTransferred).Contains("HTTP/1.1 101"))
                    {
                        try
                        {
                            socketMsg.socketAsyncEventArgs.SetBuffer(this.byte_rtxtFirst, 0, this.byte_rtxtFirst.Length);
                            if (socketMsg.socketAsyncEventArgs.AcceptSocket.Connected)
                            {
                                socketMsg.socketAsyncEventArgs.AcceptSocket.SendAsync(socketMsg.socketAsyncEventArgs);
                                lock (object_2)
                                {
                                    SendNum++;
                                }
                            }
                            goto IL_12C;
                        }
                        catch
                        {
                            goto IL_12C;
                        }
                    }
                    try
                    {
                        socketMsg.socketAsyncEventArgs.SetBuffer(this.byte_rtxtAnswer, 0, this.byte_rtxtAnswer.Length);
                        if (IsAnswer && socketMsg.socketAsyncEventArgs.AcceptSocket.Connected)
                        {
                            socketMsg.socketAsyncEventArgs.AcceptSocket.SendAsync(socketMsg.socketAsyncEventArgs);
                            lock (object_2)
                            {
                                SendNum++;
                            }
                        }
                    }
                    catch
                    {
                    }
                }
            IL_12C:
                Thread.Sleep(10);
            }
        }

        private class SocketMsg
        {
            public byte[] byte_0;
            public int bytesTransferred;
            public SocketAsyncEventArgs socketAsyncEventArgs;

            public SocketMsg(byte[] byte_0, int bytesTransferred, SocketAsyncEventArgs socketAsyncEventArgs)
            {
                this.byte_0 = byte_0;
                this.bytesTransferred = bytesTransferred;
                this.socketAsyncEventArgs = socketAsyncEventArgs;
            }

            public SocketMsg(SocketAsyncEventArgs socketAsyncEventArgs)
            {
                this.socketAsyncEventArgs = socketAsyncEventArgs;
            }
        }
    }
}
